package ph.edu.ics.sp.graphisched.gui;

import static javax.swing.GroupLayout.Alignment.LEADING;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Line2D;
import java.util.ArrayList;

import javax.swing.GroupLayout;
import javax.swing.JLabel;
import javax.swing.LayoutStyle;
import javax.swing.SwingConstants;

import ph.edu.ics.sp.graphisched.ClassBox;
import ph.edu.ics.sp.graphisched.GraphiSchedConstants;

@SuppressWarnings("serial")
public class TableMatrixPanel extends javax.swing.JPanel implements
		GraphiSchedConstants {
	private Point lineStart = new Point(0, 0);
	private Point lineEnd = new Point(0, 0);
	private ArrayList<Line2D> vlines = new ArrayList<Line2D>();
	private ArrayList<Line2D> hlines = new ArrayList<Line2D>();
	private Line2D headerLine = new Line2D.Double(lineStart, lineEnd);
	private Line2D timeHeaderLine = new Line2D.Double(lineStart, lineEnd);
	private Line2D uline = new Line2D.Double(lineStart, lineEnd);
	private JLabel numericalTime = new JLabel();
	private ArrayList<JLabel> timeArray = new ArrayList<JLabel>();
	private ArrayList<ClassBox> classes = new ArrayList<ClassBox>();
	private ArrayList<Color> colors = new ArrayList<Color>();
	private JLabel TIME_LABEL = new JLabel("Time");
	private JLabel MON_LABEL = new JLabel("Monday");
	private JLabel TUE_LABEL = new JLabel("Tuesday");
	private JLabel WED_LABEL = new JLabel("Wednesday");
	private JLabel THURS_LABEL = new JLabel("Thursday");
	private JLabel FRI_LABEL = new JLabel("Friday");
	private JLabel SAT_LABEL = new JLabel("Saturday");
	private String room;

	/**
	 * default Constructor
	 */
	public TableMatrixPanel() {
		super();
		int i;
		for (i = 0; i < 7; i++) {
			vlines.add(new Line2D.Double(lineStart, lineEnd));
		}
		for (i = 0; i < 25; i++) {
			hlines.add(new Line2D.Double(lineStart, lineEnd));
		}
		initGUI();
	}

	/**
	 * initialize graphical user interface
	 */
	private void initGUI() {
		// set panel properties
		this.setBackground(Color.white);
		this.setSize(TABLE_PANE_WIDTH, TABLE_PANE_HEIGHT);
		// set line properties
		int i;
		this.timeHeaderLine.setLine(0d, 0d, 0d, (double) TABLE_PANE_HEIGHT);
		for (i = 0; i < 7; i++) {
			float x1, y1, x2, y2;
			x1 = 0f;
			x2 = (float) TABLE_PANE_HEIGHT;
			y1 = (float) i * ((TABLE_PANE_WIDTH - TIME_HEADER_WIDTH) / 6)
					+ TIME_HEADER_WIDTH;
			y2 = (float) y1;
			this.vlines.get(i).setLine(y1, x1, y2, x2);
		}
		this.headerLine.setLine(0d, (double) HEADER_HEIGHT,
				(double) TABLE_PANE_WIDTH, (double) HEADER_HEIGHT);
		for (i = 0; i < 25; i++) {
			float x1, y1, x2, y2;
			if (i % 2 != 0)
				x1 = (float) TIME_HEADER_WIDTH;
			else
				x1 = 0f;
			x2 = (float) TABLE_PANE_WIDTH;
			y1 = (float) i * ((TABLE_PANE_HEIGHT - HEADER_HEIGHT) / 24)
					+ HEADER_HEIGHT;
			y2 = (float) y1;
			this.hlines.get(i).setLine(x1, y1, x2, y2);
		}
		this.uline.setLine(0d, 0d, 525d, 0d);

		// store time headers to array of jlabels
		for (i = 7; i < 13; i++) {
			StringBuffer sb = new StringBuffer();
			sb.append(i);
			sb.append(":00-");
			if (i != 12)
				sb.append(i + 1);
			else
				sb.append(1);
			sb.append(":00");
			numericalTime = new JLabel();
			numericalTime.setText(sb.toString());
			numericalTime.setHorizontalAlignment(JLabel.LEFT);
			timeArray.add(numericalTime);
		}
		for (i = 1; i < 7; i++) {
			StringBuffer sb = new StringBuffer();
			sb.append(i);
			sb.append(":00-");
			sb.append(i + 1);
			sb.append(":00");
			numericalTime = new JLabel();
			numericalTime.setText(sb.toString());
			numericalTime.setHorizontalAlignment(JLabel.LEFT);
			timeArray.add(numericalTime);
		}

		// layout table headers
		GroupLayout layout = new GroupLayout(this);
		layout.setAutoCreateGaps(true);
		layout.setAutoCreateContainerGaps(true);
		this.setLayout(layout);
		// begin layout
		layout.setHorizontalGroup(layout.createSequentialGroup().addGroup(
				layout.createParallelGroup(GroupLayout.Alignment.CENTER)
						.addComponent(TIME_LABEL, GroupLayout.PREFERRED_SIZE,
								52, GroupLayout.PREFERRED_SIZE).addComponent(
								timeArray.get(0))
						.addComponent(timeArray.get(1)).addComponent(
								timeArray.get(2))
						.addComponent(timeArray.get(3)).addComponent(
								timeArray.get(4))
						.addComponent(timeArray.get(5)).addComponent(
								timeArray.get(6))
						.addComponent(timeArray.get(7)).addComponent(
								timeArray.get(8))
						.addComponent(timeArray.get(9)).addComponent(
								timeArray.get(10)).addComponent(
								timeArray.get(11))).addPreferredGap(
				LayoutStyle.ComponentPlacement.RELATED,
				GroupLayout.DEFAULT_SIZE, Short.SIZE).addComponent(MON_LABEL)
				.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.SIZE).addComponent(
						TUE_LABEL).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.SIZE).addGroup(
						layout.createParallelGroup(
								GroupLayout.Alignment.LEADING).addComponent(
								WED_LABEL, GroupLayout.PREFERRED_SIZE, 70,
								GroupLayout.PREFERRED_SIZE)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.SIZE).addComponent(
						THURS_LABEL).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(FRI_LABEL).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(SAT_LABEL)

		);

		layout.linkSize(SwingConstants.HORIZONTAL, TIME_LABEL, MON_LABEL,
				TUE_LABEL);

		layout.setVerticalGroup(layout.createSequentialGroup().addGroup(
				layout.createParallelGroup(LEADING).addComponent(TIME_LABEL)
						.addComponent(MON_LABEL).addComponent(TUE_LABEL)
						.addComponent(WED_LABEL).addComponent(THURS_LABEL)
						.addComponent(FRI_LABEL).addComponent(SAT_LABEL))
				.addComponent(timeArray.get(0)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(1)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(2)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(3)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(4)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(5)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(6)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(7)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(8)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(9)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(10)).addPreferredGap(
						LayoutStyle.ComponentPlacement.RELATED,
						GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
				.addComponent(timeArray.get(11)));
		// end layout
	}

	/**
	 * draw lines and rectangles
	 */
	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		int i;
		g2.setStroke(STROKE_LINE);
		g2.setColor(Color.black);
		// draw shape of line
		g2.draw(timeHeaderLine);
		g2.draw(headerLine);
		for (i = 0; i < 7; i++)
			g2.draw(vlines.get(i));
		for (i = 0; i < 25; i++)
			g2.draw(hlines.get(i));
		g2.draw(uline);
		// draw shape of rectangle
		if (classes.size() > 0) {
			for (i = 0; i < classes.size(); i++) {
				ArrayList<Point> pts = new ArrayList<Point>();
				pts = classes.get(i).getPoints();
				int ht = classes.get(i).getHeight();
				String subj = classes.get(i).getSubject().getCourseCode();
				String section = classes.get(i).getSection();
				for (int j = 0; j < pts.size(); j++) {
					Point pt = pts.get(j);
					g2.setColor(classes.get(i).getColor());
					g2.fillRect(pt.x, pt.y, BOX_WIDTH, ht);
					g2.setStroke(STROKE_RECT);
					g2.setColor(Color.black);
					g2.drawRect(pt.x, pt.y, BOX_WIDTH, ht);
					FontMetrics fm = g2.getFontMetrics();
					int width = fm.stringWidth(subj);
					// g2.drawString(subj, pt.x+(BOX_WIDTH-width)/2,
					// pt.y+ht/2+5);
					g2.drawString(subj, pt.x + (BOX_WIDTH - width) / 2, pt.y
							+ ht / 2 - 1);
					width = fm.stringWidth(section);
					int height = fm.getHeight();
					g2.drawString(section, pt.x + (BOX_WIDTH - width) / 2, pt.y
							+ ht / 2 - 1 + height);
				}
			}
		}
	}

	/**
	 * @return the classes
	 */
	public ArrayList<ClassBox> getClasses() {
		return classes;
	}

	/**
	 * @param classes
	 *            the classes to set
	 */
	public void setClasses(ArrayList<ClassBox> classes) {
		this.classes = classes;
	}

	/**
	 * @return the colors
	 */
	public ArrayList<Color> getColors() {
		return colors;
	}

	/**
	 * @param colors
	 *            the colors to set
	 */
	public void setColors(ArrayList<Color> colors) {
		this.colors = colors;
	}

	public void addColor(Color color) {
		this.colors.add(color);
	}

	/**
	 * @return the room
	 */
	public String getRoom() {
		return room;
	}

	/**
	 * @param room
	 *            the room to set
	 */
	public void setRoom(String room) {
		this.room = room;
	}
}
